﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SharpShare {
    public static class ParsingExtensions {
        public static T? As<T>(this object value) where T : struct {
            if (value is T)
                return (T)value;
            return default(T);
        }

        public static string AsString(this object value) {
            if (value == null)
                return null;
            return value.ToString();
        }
        public static TEnumValue? AsEnum<TEnumValue>(this object value) where TEnumValue : struct {
            if (!typeof(TEnumValue).IsEnum)
                throw new InvalidOperationException("Type parameter TEnumValue is not an enum type.");

            if (value == null)
                return null;
            if (value is TEnumValue)
                return (TEnumValue)value;

            int? number = value.AsInteger();

            if (number.HasValue) {
                TEnumValue numberEnumValue = (TEnumValue)((object)number.Value);
                if (System.Enum.IsDefined(typeof(TEnumValue), numberEnumValue)) {
                    return numberEnumValue;
                }
            }

            string valueString = value.ToString();
            TEnumValue result;
            if (System.Enum.TryParse<TEnumValue>(valueString, true, out result)) {
                return result;
            }

            return null;
        }

        public static bool? AsBoolean(this object value) {
            if (value == null)
                return null;
            if (value is bool)
                return (bool)value;
            decimal? parsed = value.AsDecimal();
            if (!parsed.HasValue) {
                string stringValue = value.ToString();
                if (stringValue == null)
                    return null;

                if (stringValue.StartsWith("t", StringComparison.OrdinalIgnoreCase)
                    || stringValue.StartsWith("y", StringComparison.OrdinalIgnoreCase)
                    || stringValue.StartsWith("1", StringComparison.OrdinalIgnoreCase))
                    return true;

                return false;
            }

            return (parsed.Value > 0);
        }
        public static int? AsInteger(this object value) {
            if (value == null)
                return null;
            if (value is int) {
                return (int)value;
            }
            decimal? parsed = value.AsDecimal();
            if (!parsed.HasValue)
                return null;
            return (int)parsed.Value;
        }
        public static long? AsLong(this object value) {
            if (value == null)
                return null;
            if (value is long) {
                return (long)value;
            }
            decimal? parsed = value.AsDecimal();
            if (!parsed.HasValue)
                return null;
            return (long)parsed.Value;
        }
        public static double? AsDouble(this object value) {
            if (value == null)
                return null;
            if (value is double)
                return (double)value;
            decimal? parsed = value.AsDecimal();
            if (!parsed.HasValue)
                return null;
            return (double)parsed.Value;
        }

        public static float? AsFloat(this object value) {
            if (value == null)
                return null;
            if (value is float)
                return (float)value;
            decimal? parsed = value.AsDecimal();
            if (!parsed.HasValue)
                return null;
            return (float)parsed.Value;
        }
        public static decimal? AsDecimal(this object value) {
            if (value == null)
                return null;
            if (value is decimal)
                return (decimal)value;
            string stringValue = value.ToString();
            decimal parsedDecimal;
            if (decimal.TryParse(stringValue, out parsedDecimal)) {
                return parsedDecimal;
            }
            return null;
        }
    }

    public static class AttributeExtensions {
        public static TAttribute GetCustomAttribute<TAttribute>(this System.Reflection.ICustomAttributeProvider provider, bool inherit = true)
            where TAttribute : Attribute {
            return provider.GetCustomAttributes<TAttribute>(inherit).FirstOrDefault();
        }
        public static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>(this System.Reflection.ICustomAttributeProvider provider, bool inherit = true)
            where TAttribute : Attribute {
            if (provider == null) throw new ArgumentNullException("provider");
            TAttribute[] attrs = (TAttribute[])provider.GetCustomAttributes(typeof(TAttribute), inherit);
            return attrs;
        }
    }
}
